// 接口鉴权

import { CanActivate, ExecutionContext, UnauthorizedException, BadRequestException, Injectable } from "@nestjs/common";
import Config from '@/config';
import { Reflector } from '@nestjs/core';
import { BaseDao } from '@/common/baseDao/base.service';
import { Util } from '@/common/util/util.service';
@Injectable()
export class PermissionGuard implements CanActivate {

    constructor(
        private readonly reflector: Reflector,
        private readonly baseDao: BaseDao,
        private readonly util: Util
    ) { }

    async canActivate(context: ExecutionContext): Promise<boolean> {
        const handler = context.getHandler(); // 获取当前处理函数
        const controller = context.getClass(); // 获取当前控制器类
        
       // 获取函数级别元数据
       let isNoAuth = this.reflector.get<string>('isNoAuth', handler) || this.reflector.get<string>('isNoAuth', controller);
        const request: Request = context.switchToHttp().getRequest();
        // 如果不需要token验证，直接返回true
        if (isNoAuth) {
            return true
        } else {
            // throw new BadRequestException('接口暂无权限!');
        }
        const { role } = request['userInfo'];
        const permissionsData = await this.baseDao.selects({
            dbName: "quick-roles",
            getMain:true,
            whereJson: {
                role_id: this.util._.in(role)
            },
            fieldJson: {
                // permission: true
            },
            foreignDB: [
                {
                    dbName: "quick-permissions",
                    localKey: "permission", // 主表外键字段名
                    foreignKey: "permission_id", // 副表外键字段名
                    as: "user_permission",  //副表as字段
                    unwind: false, //笛卡尔积
                    // // 副表字段显示规则
                    fieldJson: {
                        // url: true
                    },
                    // // 副表排序规则
                }
            ]
        })
        // 检查返回的数据类型
        if (permissionsData && !Array.isArray(permissionsData)) {
            // console.log('permissionsData',permissionsData)
            // 如果是单个对象
            const {user_permission, role_id} = permissionsData as { role_id: string,user_permission: { url: string[], permission_id: string }[],};
            const {menu} = permissionsData as {menu: string[] };
            request['menus'] = menu; // 将菜单数组添加到请求对象中

            const permissionsUrls =  [...this.util.flattenArray(user_permission,'url'),'/admin/auth/*']
            if(role_id === Config.sysIdentifier) return true //如果是超级管理员，直接返回true
            
            if(this.matchesPatterns(request.url, permissionsUrls)){
                return true
            }else{
                throw new BadRequestException('接口暂无权限!');
            }
        }else{
            throw new BadRequestException('接口暂无权限!');
        }

    }
    // 检查当前请求路径是否有权限
    private matchesPatterns(url: string, patterns: string[]): boolean {
        // 遍历所有模式并检查是否匹配
        return patterns.some(pattern => {
            // 将模式中的 `*` 替换为正则表达式中的 `.*`
            const regexPattern = pattern.replace('*', '.*');
            const regex = new RegExp(`^${regexPattern}$`);  // 从头到尾匹配
            return regex.test(url);
        });
    }
}